2023/12/231957字符

通道

非缓冲通道

  • 无论是向通道中写入数据还是读取数据,都会发生阻塞。发送/读取结束后解除阻塞;
  • 一次发送,一次接收,都是阻塞的(发送与接收次数不一致会发生死锁)。
package main

import "fmt"

func main() {
    var ch chan bool
    ch = make(chan bool)

    go func() {
        fmt.Print(1111111)
        ch <- true  // 向通道中写入数据
    }()

    data := <- ch  // 从通道中读取数据
    fmt.Println(data)
}

关闭通道

package main

import (
    "fmt"
    "time"
)

func main() {
    ch := make(chan int)
    go sendData(ch)
    for v := range ch {
        fmt.Print(v) //--> 01234
    }
    fmt.Println("end") //--> end
}

func sendData(ch chan int) {
    for i := 0; i < 5; i++ {
        time.Sleep(1 * time.Second)
        ch <- i
    }
    close(ch) // 通知对方,关闭通道
}

缓冲通道

  • 发送:缓冲区数据满了,才会发生阻塞;
  • 接收:缓冲区数据为空,才会发生阻塞。

非缓冲通道 可以理解为是一个大小为 1 的缓冲通道

package main

import (
    "fmt"
)

func main() {
    ch := make(chan int, 2) // 缓冲通道,缓冲区大小为 2
    go sendData(ch)
    for {
        v, ok := <-ch
        if !ok { // 通道满了,退出循环
            fmt.Println("readend")
            break
        }
        fmt.Println("read:", v, "len:", len(ch))
    }
    fmt.Println(len(ch))
}

func sendData(ch chan int) {
    for i := 1; i <= 5; i++ {
        ch <- i
        fmt.Println("write", i)
    }
    close(ch)
}

双向通道

  • var ch = make(chan int) 双向通道
  • var ch = make(chan <- int) 单项通道:只能写,不能读
  • var ch = make(<- chan int) 单项通道:只能读,不能写
package main

import (
    "fmt"
)

func main() {
    ch := make(chan int)
    done := make(chan bool)
    go sendData(ch, done)
    num := <-ch
    fmt.Println(num)

    <-done // 等待协程结束
    fmt.Println("end")
}

func sendData(ch chan int, done chan bool) {
    ch <- 10
    done <- true // 通知结束
}